package com.canace.novel.serviece.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.canace.novel.core.common.constant.ErrorCodeEnum;
import com.canace.novel.core.common.resp.RestResp;
import com.canace.novel.core.constant.DatabaseConsts;
import com.canace.novel.core.constant.SystemConfigConsts;
import com.canace.novel.core.util.JwtUtils;
import com.canace.novel.dao.entity.UserInfo;
import com.canace.novel.dao.mapper.UserInfoMapper;
import com.canace.novel.dto.req.UserLoginReqDto;
import com.canace.novel.dto.req.UserRegisterReqDto;
import com.canace.novel.dto.resp.UserLoginRegisterRespDto;
import com.canace.novel.manager.redis.VerifyCodeManager;
import com.canace.novel.serviece.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author canace
 * @version 1.0
 * @description 用户服务实现类
 * @date 2024/1/20 12:31
 */

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final VerifyCodeManager verifyCodeManager;

    private final UserInfoMapper userInfoMapper;

    private final JwtUtils jwtUtils;
    @Override
    public RestResp<UserLoginRegisterRespDto> userRegister(UserRegisterReqDto registerReqDto) {
        // UserRegisterReqDto已经对参数要求进行了限制，这里只需要对数据进行判断即可
        // 判断验证码是否正确
        if(!verifyCodeManager.imgVerifyCodeOk(registerReqDto.getSessionId(),registerReqDto.getVelCode())){
            return RestResp.fail(ErrorCodeEnum.USER_VERIFY_CODE_ERROR);
        }
        // 判断用户名是否已经被注册
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq(DatabaseConsts.UserInfoTable.COLUMN_USERNAME, registerReqDto.getUsername());
        if(userInfoMapper.selectCount(userInfoQueryWrapper) > 0){
            return RestResp.fail(ErrorCodeEnum.USER_NAME_EXIST);
        }

        // 将信息保存至数据库
        UserInfo userInfo = new UserInfo();
        userInfo.setPassword(DigestUtils.md5DigestAsHex(registerReqDto.getPassword().getBytes(StandardCharsets.UTF_8)));
        userInfo.setUsername(registerReqDto.getUsername());
        userInfo.setNickName(registerReqDto.getUsername());
        userInfo.setCreateTime(LocalDateTime.now());
        userInfo.setUpdateTime(LocalDateTime.now());
        userInfo.setSalt("0");
        userInfoMapper.insert(userInfo);

        // 删除验证码
        verifyCodeManager.removeImgVerifyCode(registerReqDto.getSessionId());

        UserLoginRegisterRespDto userLoginRegisterRespDto = getUserLoginRegisterRespDto(userInfo);

        return RestResp.ok(userLoginRegisterRespDto);
    }

    /**
     * 为用户生成Jwt，并返回封装结果
     * @param userInfo 用户信息
     * @return 封装结果
     */
    private UserLoginRegisterRespDto getUserLoginRegisterRespDto(UserInfo userInfo) {
        // 生成jwt
        String s = jwtUtils.generateToken(userInfo.getId(), SystemConfigConsts.NOVEL_FRONT_KEY);

        // 封装返回结果
        UserLoginRegisterRespDto userLoginRegisterRespDto = new UserLoginRegisterRespDto();
        userLoginRegisterRespDto.setUid(userInfo.getId());
        userLoginRegisterRespDto.setNickName(userInfo.getNickName());
        userLoginRegisterRespDto.setToken(s);
        return userLoginRegisterRespDto;
    }

    @Override
    public RestResp<UserLoginRegisterRespDto> userLogin(UserLoginReqDto dto) {
        // 先查询用户是否存在
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq(DatabaseConsts.UserInfoTable.COLUMN_USERNAME, dto.getUsername());
        UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
        if(ObjectUtils.isEmpty(userInfo)){
            return RestResp.fail(ErrorCodeEnum.USER_ACCOUNT_NOT_EXIST);
        }
        // 然后比较密码
        if(!userInfo.getPassword().equals(DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8)))){
            return RestResp.fail(ErrorCodeEnum.USER_PASSWORD_ERROR);
        }

        UserLoginRegisterRespDto userLoginRegisterRespDto = getUserLoginRegisterRespDto(userInfo);

        return RestResp.ok(userLoginRegisterRespDto);

    }
}
